﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnitTests;
using System.Diagnostics;
using System.Threading;
using Warburton.FastBitArray;
using Warburton.FastBitArray.Factories;

namespace Performance
{
    class Program
    {
        static void RunSuite(string name, BaseSuite suite)
        {
            Console.WriteLine(name);
            Thread.Sleep(1000);
            var sw = Stopwatch.StartNew();
            suite.TestUpTo513Bits();
            suite.TestAnd();
            suite.TestOr();
            suite.TestXor();
            suite.TestNot();
            suite.TestSetAll();
            Console.WriteLine(sw.ElapsedMilliseconds);
        }

        static void LongBitArraysTest(string name, IBitArrayFactory factory)
        {
            Console.WriteLine("Perf "+ name);
            Thread.Sleep(2000);
            var sw = Stopwatch.StartNew();

            var primes = BaseSuite.Primes;

            var lastPrime = primes.Last();

            var bitArrays = new List<IBitArray>();
            for (int i=0; i < primes.Count; ++i)
            {
                var bitArray = factory.BitArray(lastPrime * 20);
                var prime = primes[i];
                for (int j = 0; j < bitArray.NumberOfBits; j += prime)
                    bitArray.Set(j, true);
                bitArrays.Add(bitArray);
            }

            var r = new Random(0);

            Console.WriteLine(sw.ElapsedMilliseconds);

            for (int i = 0; i < 10000000; ++i)
            {
                var array1 = bitArrays[r.Next(0, bitArrays.Count)];
                var array2 = bitArrays[r.Next(0, bitArrays.Count)];

                switch (r.Next(0, 4))
                {
                    case 0:
                        array1.Or(array2);
                        break;

                    case 1:
                        array1.And(array2);
                        break;

                    case 2:
                        array1.Xor(array2);
                        break;

                    case 3:
                        array1.Not();
                        array2.Not();
                        break;

                    default:
                        throw new InvalidOperationException();
                }
            }
            Console.WriteLine(sw.ElapsedMilliseconds);
        }

        static void Main(string[] args)
        {
            //RunSuite("DefaultSuite", new DefaultSuite());
            //RunSuite("Unsafe64BitSuite", new Safe64BitSuite());
            //RunSuite("Unsafe64BitSuite", new Unsafe64BitSuite());

            LongBitArraysTest("default",  DefaultFactory.Instance);
            LongBitArraysTest("unsafe64", Unsafe64BitFactory.Instance);
            LongBitArraysTest("safe64",   Safe64BitFactory.Instance);
            LongBitArraysTest("unsafe32", Unsafe32BitFactory.Instance);
            LongBitArraysTest("sse64",    SSE64BitFactory.Instance);
        }
    } 
}
